from OpenGL.GL               import *
from OpenGL.GLU              import *
from OpenGL.GLUT             import *
from random                  import random, randint
from gobjects                import Sphere, GObject, Tetrahedron, \
                                    Cylinder, Scene, Arrow
from fonts                   import regularFont, tooltipFont



class TestSceneGenerator(object):
    def __init__(self):
        pass
    
    def get3DScene(self, canvas):
        self.scene3d = TestScene(canvas)
        return self.scene3d
    
    def getOverlayScene(self, canvas):
        self.overlay = TestOverlay(canvas)
        return self.overlay
    
    
class TestScene(Scene):
    def __init__(self, canvas):
        Scene.__init__(self, canvas)
        nSpheres = 10
        self.nSpheres = nSpheres
        self.col = [(random(), random(), random(), 1.0)
               for x in range(nSpheres)]
        self.pos = [(randint(-30, 30), randint(2, 20), randint(-30,30))
               for i in range(nSpheres)]
        self.radii = [random()*2 + 0.5 for x in range(nSpheres)]
        self.spheres = map(self.addChild, [Sphere(self, self.pos[x][0], self.pos[x][1], self.pos[x][2],
                               self.radii[x], color=self.col[x],
                               tooltip='Sphere %04d'%x) for x in range(nSpheres)])
        nCylinders = 10
        self.nCyls = nCylinders
        self.col = [(random(), random(), random(), 1.0)
               for x in range(nCylinders)]
        self.pos = [(randint(-30, 30), randint(2, 20), randint(-30,30))
               for i in range(nCylinders)]
        self.radii = [random()*2 + 0.5 for x in range(nCylinders)]
        self.cylinders = map(self.addChild, [Cylinder(self, self.pos[x][0], self.pos[x][1], self.pos[x][2],
                                                      self.pos[x][0], self.pos[x][1]+3, self.pos[x][2]+7,
                               self.radii[x], color=self.col[x],
                               tooltip='Cylinder %04d'%x) for x in range(nCylinders)])
        
        nTdrons = 10
        color = [(random(), random(), random(), 1.0)
               for x in range(nTdrons)]
        pos = [(randint(-50, 50), randint(2, 20), randint(-50,50))
               for i in range(nTdrons)]
        tDrons = map(self.addChild, [Tetrahedron(self, pos[x][0], pos[x][1], pos[x][2],
                               color=color[x], tooltip='TetraHedron %04d'%x).scale(5,5,5) for x in range(nTdrons)])
        
class TestOverlay(Scene):
    def __init__(self, canvas):
        Scene.__init__(self, canvas)
        self.axes = Arrow(self, 0, 0, 0, tooltip='Axes').scale(5, 5, 5)
        
    def render(self):
        glMatrixMode(GL_MODELVIEW)
        glPushMatrix()
        glLoadIdentity()
        
        glMatrixMode(GL_PROJECTION)
        glPushMatrix()
        glLoadIdentity()
        
        w, h = self.canvas.windowSize
        size = max(w, h) / 2.0
        aspect = float(w) / float(h)
        if w <= h:
            aspect = float(h) / float(w)
            glOrtho(-size, size, -size*aspect, size*aspect, -100000.0, 100000.0)
        else:
            glOrtho(-size*aspect, size*aspect, -size, size, -100000.0, 100000.0)
        glScaled(aspect, aspect, 1.0)
        
        glMatrixMode(GL_MODELVIEW)
        
        glPushAttrib(GL_LIGHTING_BIT| GL_DEPTH_BITS)
        
        
        glTranslate(-w/2 + 40, -h/2 + 40, 99950)
        self.canvas.camera.applyRotations()
        self.axes.render()

        glDisable(GL_LIGHTING)
        glDisable(GL_DEPTH_TEST)
        glShadeModel(GL_SMOOTH)
        
        glLoadIdentity()
        self.showCameraCoordinates()
        
        glPopAttrib()
        glPopMatrix()
        
        glMatrixMode(GL_PROJECTION)
        glPopMatrix()
        for child in self.children:
            child.render()
        
        
    def showCameraCoordinates(self):
        # draw children
        
        cc = self.canvas.camera.getState()
        labels = ('x', 'y', 'z', 'tilt', 'pan')
        args = []
        for i in range(len(cc)):
            args.append(labels[i])
            args.append(cc[i])
                       
        msg = ("%5s %8.2f\n"*5).strip()
        msg = msg%tuple(args)
        
        self.showMessage(msg, 20)
        

            
    def showMessage(self, msg, padding):
        if not msg:
            return
        lines = msg.split('\n')
        bbxs = [regularFont.BBox(line) for line in lines]
        
        ipadding = 5
        wpadding = padding
        
        mHeight = max([b[4] for b in bbxs])
        height  = mHeight*len(lines) + ipadding*(len(lines) + 1)
        width   = max([b[3] for b in bbxs]) + ipadding*2
        
        w, h = self.canvas.windowSize

        r = w/2 - wpadding
        b = wpadding - h/2
        t = b + height
        l = r - width
        cx = (r + l)/2
        cy = (b + t)/2
        
        glTranslate(l, b, 0)
        
        glColor4f(0, 0, 0, 0.4)
        glBegin(GL_TRIANGLE_STRIP)
        glVertex3f(0, 0, 0)
        glVertex3f(width, 0, 0)
        glVertex3f(0, height, 0)
        glVertex3f(width, height, 0)
        glEnd()
        
        glColor4f(1, 1, 1, 1)
        for i, line in enumerate(reversed(lines)):
            glPushMatrix()
            glTranslate(ipadding, ipadding*(i+1) + mHeight*i, 0)
            regularFont.Render(line)
            glPopMatrix()
            
    

def main():
    import wx
    from canvas3d import Canvas3D
    from timestat import timestat
    from wx.glcanvas             import WX_GL_RGBA, WX_GL_DOUBLEBUFFER

    
    app = wx.App()
    frame3D = wx.Frame(None, -1, "Canvas 3D", wx.Point(1100, 50), wx.Size(800,400))
    canvas = Canvas3D(frame3D, WX_GL_RGBA, WX_GL_DOUBLEBUFFER)
    frame3D.Show()
    app.MainLoop()
    print "Exiting main loop\n"
    timestat.printStats()
    
if __name__ == '__main__':
    main()
    